package net.callumtaylor.swipetorefresh.helper;
import net.callumtaylor.pulltorefresh.R;
import net.callumtaylor.swipetorefresh.view.OnOverScrollListener;
import net.callumtaylor.swipetorefresh.view.RefreshableListView;
import net.callumtaylor.swipetorefresh.view.RefreshableScrollView;
import android.app.Activity;
import android.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.animation.AccelerateInterpolator;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
* This is the refresh helper class which you could call to
* wrap your refreshable views and activity to.
*
* You can call {@link RefreshHelper#showHelper()} to show the indeterminate progress
* or {@link RefreshHelper#hideHelper()} to hide. This is useful when having more than one
* refreshable list fragments in a view pager, call show/hide on the
* relevant fragment when switching page to prevent multiple refreshables
* from showing.
*/
public class RefreshHelper implements OnOverScrollListener
{
private final View ptrOverlay;
private final ProgressBar ptrProgressBar, ptrInderterminateProgressBar;
private final AccelerateInterpolator accelerationInterpolator;
private final View abRoot;
private OnRefreshListener refreshListener;
private RefreshableListView listView;
private RefreshableScrollView scrollView;
private boolean refreshing = false;
private Runnable reset = new Runnable()
{
@Override public void run()
{
if (ptrOverlay.getAnimation() == null)
{
resetOverlay();
}
}
};
private RefreshHelper(View overlay, View progressOverlay, View root)
{
this.ptrOverlay = overlay;
this.ptrInderterminateProgressBar = (ProgressBar)progressOverlay;
this.accelerationInterpolator = new AccelerateInterpolator();
this.ptrProgressBar = (ProgressBar)overlay.findViewById(R.id.refresh_progress);
this.abRoot = root;
ptrProgressBar.setMax(0);
ptrProgressBar.setMax(100);
ptrProgressBar.setProgress(0);
}
public void setRefreshing(boolean refreshing)
{
this.refreshing = refreshing;
}
public boolean isRefreshing()
{
return refreshing;
}
public void hideHelper()
{
if (isRefreshing())
{
ptrInderterminateProgressBar.setVisibility(View.GONE);
}
}
public void showHelper()
{
if (isRefreshing())
{
ptrInderterminateProgressBar.setVisibility(View.VISIBLE);
}
}
@Override public void onBeginRefresh()
{
onRefreshScrolledPercentage(1.0f);
AnimationHelper.pullRefreshActionBar(ptrOverlay, abRoot);
}
/**
* Alias for {@link RefreshHelper#onRefresh()}
*/
public void refresh()
{
onRefresh();
}
@Override public void onRefresh()
{
if (scrollView != null)
{
scrollView.setCanRefresh(false);
}
if (listView != null)
{
listView.setCanRefresh(false);
}
refreshing = true;
ptrProgressBar.setVisibility(View.GONE);
ptrInderterminateProgressBar.setVisibility(View.VISIBLE);
((TextView)ptrOverlay.findViewById(R.id.refresh_text)).setText(R.string.ptr_refreshing);
ptrOverlay.postDelayed(reset, 800);
if (refreshListener != null)
{
refreshListener.onRefresh();
}
}
@Override public void onRefreshScrolledPercentage(float percentage)
{
ptrProgressBar.setVisibility(View.VISIBLE);
ptrProgressBar.setProgress(Math.round(accelerationInterpolator.getInterpolation(percentage) * 100));
}
/**
* Alias for {@link RefreshHelper#onReset()}
*/
public void finish()
{
onReset();
}
/**
* You may call this method after the refreshable method has completed
* to reset the ptr functionality
*/
@Override public void onReset()
{
refreshing = false;
if (ptrInderterminateProgressBar.getVisibility() == View.VISIBLE)
{
AnimationHelper.fadeOut(ptrInderterminateProgressBar);
}
ptrOverlay.removeCallbacks(reset);
resetOverlay();
if (scrollView != null)
{
scrollView.setCanRefresh(true);
scrollView.onRefreshComplete();
}
if (listView != null)
{
listView.setCanRefresh(true);
listView.onRefreshComplete();
}
}
private void resetOverlay()
{
if (ptrOverlay.getVisibility() == View.VISIBLE)
{
AnimationHelper.pullRefreshActionBarCancel(ptrOverlay, abRoot);
ptrProgressBar.setVisibility(View.GONE);
ptrProgressBar.setProgress(0);
ptrOverlay.postDelayed(new Runnable()
{
@Override public void run()
{
((TextView)ptrOverlay.findViewById(R.id.refresh_text)).setText(R.string.ptr_pull);
}
}, 400);
}
else
{
((TextView)ptrOverlay.findViewById(R.id.refresh_text)).setText(R.string.ptr_pull);
}
}
public void setOnRefreshListener(OnRefreshListener l)
{
this.refreshListener = l;
}
public void setRefreshableListView(RefreshableListView l)
{
if (l != null)
{
this.listView = l;
this.listView.setOnOverScrollListener(this);
}
}
public void setRefreshableScrollView(RefreshableScrollView l)
{
if (l != null)
{
this.scrollView = l;
this.scrollView.setOnOverScrollListener(this);
}
}
private static View findActionBar(Window w)
{
return getFirstChildByClassName((ViewGroup)w.getDecorView(), "com.android.internal.widget.ActionBarContainer");
}
private static View getFirstChildByClassName(ViewGroup parent, String name)
{
View retView = null;
int childCount = parent.getChildCount();
for (int childIndex = 0; childIndex < childCount; childIndex++)
{
View child = parent.getChildAt(childIndex);
if (child.getClass().getName().equals(name))
{
return child;
}
if (child instanceof ViewGroup)
{
View v = getFirstChildByClassName((ViewGroup)child, name);
if (v != null)
{
return v;
}
}
}
return retView;
}
private static <T extends View> T getFirstChildByInstance(ViewGroup parent, Class<T> instance)
{
View retView = null;
int childCount = parent.getChildCount();
for (int childIndex = 0; childIndex < childCount; childIndex++)
{
View child = parent.getChildAt(childIndex);
if (instance.isAssignableFrom(child.getClass()))
{
return instance.cast(child);
}
if (child instanceof ViewGroup)
{
View v = getFirstChildByInstance((ViewGroup)child, instance);
if (v != null)
{
return instance.cast(v);
}
}
}
return instance.cast(retView);
}
/**
* You can call this at the start of your activity to reset any current set refresh bar
* @param ctx
*/
public static void reset(Activity ctx)
{
ViewGroup abRoot = null;
int id = ctx.getResources().getIdentifier("action_bar_container", "id", ctx.getPackageName());
if (id > 0)
{
abRoot = (ViewGroup)ctx.getWindow().getDecorView().findViewById(id);
}
if (id == 0 || abRoot == null)
{
abRoot = (ViewGroup)findActionBar(ctx.getWindow());
}
if (abRoot != null)
{
View view = abRoot.findViewById(R.id.refresh_view);
while (view != null)
{
abRoot.removeView(view);
view = abRoot.findViewById(R.id.refresh_view);
}
View inderterminate = abRoot.findViewById(R.id.refresh_progress_inderterminate);
while (inderterminate != null)
{
abRoot.removeView(inderterminate);
inderterminate = abRoot.findViewById(R.id.refresh_progress_inderterminate);
}
}
}
public static RefreshHelper wrapRefreshable(Activity ctx, RefreshableListView list, OnRefreshListener l)
{
RefreshHelper helper = wrapRefreshable(ctx, l);
helper.setRefreshableListView(list);
return helper;
}
public static RefreshHelper wrapRefreshable(Activity ctx, RefreshableScrollView scroll, OnRefreshListener l)
{
RefreshHelper helper = wrapRefreshable(ctx, l);
helper.setRefreshableScrollView(scroll);
return helper;
}
public static RefreshHelper wrapRefreshable(Activity ctx, RefreshableListView list, RefreshableScrollView scroll, OnRefreshListener l)
{
RefreshHelper helper = wrapRefreshable(ctx, l);
helper.setRefreshableListView(list);
helper.setRefreshableScrollView(scroll);
return helper;
}
public static RefreshHelper wrapRefreshable(Fragment fragment, OnRefreshListener l)
{
RefreshHelper helper = wrapRefreshable(fragment.getActivity(), l);
RefreshableListView list = getFirstChildByInstance((ViewGroup)fragment.getView(), RefreshableListView.class);
RefreshableScrollView scroll = getFirstChildByInstance((ViewGroup)fragment.getView(), RefreshableScrollView.class);
helper.setRefreshableListView(list);
helper.setRefreshableScrollView(scroll);
return helper;
}
public static RefreshHelper wrapRefreshable(View view, OnRefreshListener l)
{
RefreshHelper helper = wrapRefreshable((Activity)view.getContext(), l);
RefreshableListView list = getFirstChildByInstance((ViewGroup)view, RefreshableListView.class);
RefreshableScrollView scroll = getFirstChildByInstance((ViewGroup)view, RefreshableScrollView.class);
helper.setRefreshableListView(list);
helper.setRefreshableScrollView(scroll);
return helper;
}
public static RefreshHelper wrapRefreshable(Activity ctx, OnRefreshListener l)
{
ViewGroup abRoot;
if ((abRoot = (ViewGroup)ctx.getWindow().getDecorView().findViewById(R.id.action_bar_container)) == null)
{
abRoot = (ViewGroup)findActionBar(ctx.getWindow());
}
if (abRoot != null)
{
View overlay = LayoutInflater.from(ctx).inflate(R.layout.abs_overlay, abRoot, false);
abRoot.addView(overlay);
View progressOverlay = LayoutInflater.from(ctx).inflate(R.layout.abs_overlay_progress, abRoot, false);
abRoot.addView(progressOverlay);
RefreshHelper helper = new RefreshHelper(overlay, progressOverlay, abRoot.getChildAt(0));
helper.setOnRefreshListener(l);
return helper;
}
return null;
}
public interface OnRefreshListener
{
public void onRefresh();
}
}